#include "FirstModule.h"


FirstModule::FirstModule(NxScene* scene, NxVec3 position): m_object(scene), m_position(position), m_scene(scene)
{}

FirstModule::~FirstModule(void)
{}

void FirstModule::CreateFirstModule(float bowlingBallStartVelocity , float toolBoxMass, float seesawDistance, float slopeAngle)
{
	//create the first slope
	NxVec3 positionFirstSlope = NxVec3(0, 20, 0) + m_position;
	CreateFirstSlope(positionFirstSlope);

	//create the bowling ball 
	NxVec3 bowlingBallPosition((float)0.6, (float)22.2, 0);
	bowlingBallPosition += m_position;
	float bowlingBallRadius = (float)0.05;
	float bowlingBallMass = 2;
	float bowlingBallDynamicFriction = 0;
	float bowlingBallStaticFriction = 0;
	float bowlingBallRestitution = 1;
	NxActor* a = m_object.CreateSphere(bowlingBallPosition, bowlingBallRadius, bowlingBallMass, bowlingBallDynamicFriction, 
		bowlingBallStaticFriction, bowlingBallRestitution);
	a->setName("bowlingBall");

	//set the initial velocity of the bowling ball
	//float initialVelocity = 4.07;
	//float initialVelocity = 9.58;
	NxVec3 initialVelocityBowlingBall((float)sin(-0.52)*bowlingBallStartVelocity, (float)-cos(-0.52)*bowlingBallStartVelocity, 0);
	a->setLinearVelocity(initialVelocityBowlingBall);

	//create the tool box
	NxVec3 toolBoxPosition((float)-3.5, (float)20.3, 0);
	toolBoxPosition += m_position;
	NxVec3 toolBoxSize((float)0.2, (float)0.2, 1);
	NxVec3 toolBoxDFsFR(0, 0, 1);
	a = m_object.CreateBox(toolBoxSize, toolBoxPosition, toolBoxDFsFR, toolBoxMass);
	a->setName("toolBox");

	//create the seesaw
	NxVec3 seesawPosition((float)-3.5 - seesawDistance, 10, 0);
	seesawPosition += m_position;
	CreateSeesaw(seesawPosition);

	//create the books
	NxVec3 bookPosition(-6- seesawDistance, 15, 0);
	bookPosition += m_position;
	NxVec3 bookSize((float)0.5, (float)0.2, (float)0.7);
	NxVec3 bookMaterial(1, 1, 0);
	float bookMass = 0.5;
	a = m_object.CreateBox(bookSize, bookPosition, bookMaterial, bookMass);
	a->setName("books");

	//create the second slope
	//NxVec3 secondSlopePosition(-8.5- seesawDistance, 10, 0);
	//secondSlopePosition += m_position;
	NxVec3 secondSlopePosition(0, 0, 0);
	secondSlopePosition+=m_position;
	secondSlopePosition += NxVec3((float)-6.16-seesawDistance -5/2*cos(slopeAngle), (float)10.89-5/2*sin(slopeAngle), 0);
	float angle = slopeAngle;
	CreateSecondSlope(secondSlopePosition, angle);

	//create the copper block
	NxVec3 copperBlockSize((float)0.5, (float)0.2, (float)0.3);
	NxVec3 copperBlockPosition((float)-5.3- seesawDistance, (float)13.6, 0);
	copperBlockPosition += m_position;
	NxVec3 copperBlockMaterial(0, 0, 0);
	float copperBlockMass = 5;
	NxActor* copperBlockActor = m_object.CreateBox(copperBlockSize, copperBlockPosition, copperBlockMaterial, copperBlockMass);
	copperBlockActor->setName("copperBlock");

	//create the wall
	NxVec3 wallSize((float)0.1, 2, 2);
	NxVec3 wallPosition((float)-8.5- seesawDistance, 10, 0);
	wallPosition += m_position;
	NxVec3 wallRotation(0, 0, 0);
	NxVec3 walldFsFR(0, 0, 1);
	m_object.CreateKinematicBox(wallSize, wallPosition, wallRotation, walldFsFR);
}

void FirstModule::CreateFirstSlope(const NxVec3& position)
{
	//create the base
	NxVec3 sizeBase(4, (float)0.1, 2);
	NxVec3 rotationBase(0, 0, 0);
	NxVec3 positionBase(position);
	NxVec3 materialProperties((float)0.165, 0, 0);
	m_object.CreateKinematicBox(sizeBase, positionBase, rotationBase, materialProperties);

	//create the slope inclined of 30 degres
	NxVec3 sizeSlope(2, (float)0.1, 2);
	NxVec3 rotationSlope(0, 0, (float)0.52);
	NxVec3 offset(-1, 1, 0);
	NxVec3 positionSlope = position + offset;
	m_object.CreateKinematicBox(sizeSlope, positionSlope, rotationSlope, materialProperties);
}
void FirstModule::CreateSecondSlope(const NxVec3& position, float angle)
{
	NxVec3 slopeSize(5, (float)0.2, 2);
	NxVec3 slopeRotation(0, 0, angle);
	NxVec3 slopePosition = position;
	NxVec3 materialProperties((float)0.3, 0, 0);
	m_object.CreateKinematicBox(slopeSize, slopePosition, slopeRotation, materialProperties);
}
NxActor* FirstModule::CreateSeesaw(const NxVec3& position)
{
	//the actor descriptor for the feet
	NxActorDesc actorFeetDesc;

	//the shape descriptor for the feet
	NxBoxShapeDesc feetDesc;
	NxVec3 feetDimensions((float)0.1, 5, (float)0.1);
	feetDesc.dimensions.set(feetDimensions);
	actorFeetDesc.shapes.push_back(&feetDesc);
	actorFeetDesc.body = 0;
	actorFeetDesc.globalPose.t = position;

	//add the actor to the scene
	NxActor* actorFeet = m_scene->createActor(actorFeetDesc);

	//the actor descriptor for the balance
	NxActorDesc actorBalanceDesc;
	
	//shape descriptor for the balance part
	NxBoxShapeDesc balanceDesc;
	balanceDesc.dimensions.set(NxVec3(4, (float)0.2, 2));
	balanceDesc.mass = (float)0.15;
	balanceDesc.localPose.M.rotZ(0.50);
	actorBalanceDesc.shapes.push_back(&balanceDesc);

	//actor property
	NxBodyDesc bodyDesc;
	actorBalanceDesc.body = &bodyDesc;
	actorBalanceDesc.density = 10;
	NxVec3 offset(0, (float)(feetDimensions.y+0.5), 0);
	actorBalanceDesc.globalPose.t = position+offset;

	//shape for the blocker
	NxBoxShapeDesc blockerShape;
	blockerShape.dimensions.set((float)0.1, (float)1.2, (float)0.5);
	blockerShape.localPose.t = NxVec3(-2.5, -3, 0);
	blockerShape.localPose.M.rotZ(0.50);
	blockerShape.mass = (float)0.05;
	actorBalanceDesc.shapes.push_back(&blockerShape);

	NxActor* actorBalance = m_scene->createActor(actorBalanceDesc);

	//create the joint
	NxRevoluteJointDesc joint;
	joint.actor[1] = 0;
	joint.actor[0] = actorBalance;

	NxVec3 anchor = position + feetDimensions;

	joint.setGlobalAnchor(anchor);
	joint.setGlobalAxis(NxVec3(0, 0, 1));

	joint.jointFlags =NX_JF_COLLISION_ENABLED;

	joint.projectionMode = NX_JPM_POINT_MINDIST;
	joint.projectionDistance = 0;
	joint.projectionAngle = (float)0.0872;

	NxJoint* newJoint = m_scene->createJoint(joint);


	//create the block
	NxActorDesc actorBlockDesc;

	//the shape descriptor for the feet
	NxBoxShapeDesc blockDesc;
	NxVec3 blockDimensions((float)0.7, (float)0.1, (float)0.1);
	blockDesc.dimensions.set(blockDimensions);
	blockDesc.localPose.M.rotZ((float)-3.14/4);
	actorBlockDesc.shapes.push_back(&blockDesc);
	actorBlockDesc.body = 0;
	actorBlockDesc.globalPose.t = position + feetDimensions + NxVec3(-1, -1, (float)-0.1);

	//add the actor to the scene
	m_scene->createActor(actorBlockDesc);
	return 0;
}